package deng.hibernate.test.blob.createblob;

import java.io.*;
import java.lang.reflect.Proxy;
import java.util.*;
import java.sql.*;

import javax.persistence.*;

import org.apache.commons.io.IOUtils;
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.jdbc.Work;

public class EntitytManagerMain {
	
	private EntityManager entityManager;
	
	public static void main(String[] args) {
		new EntitytManagerMain().run();
	}

	/** Load META-INF/persistence.xml in classpath. */
	public void run() {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("testdb");
		entityManager = emf.createEntityManager();
		EntityTransaction tx = entityManager.getTransaction();
		try {
			tx.begin();
			runExample();
			tx.commit();
		} catch (Throwable e) {
			if (tx.isActive()) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			entityManager.close();
			emf.close();
		}
	}

	private void runExample() throws Exception {
		//System.out.println("EM delegate: " + entityManager.getDelegate());
		runCreateData();
		runQuery();
	}
	
	private void runCreateData() throws Exception {
		String name = "hibernate_logo.gif";
		InputStream resInputStream = getClass().getClassLoader().getResourceAsStream("samples/" + name);
		byte[] blobBytes = IOUtils.toByteArray(resInputStream);
		
		Image e = new Image();
		e.setName(name);
		e.setNameBytes(name.getBytes());
		
		// This works vs the ThreadLocalSessionContext!
		Session session = entityManager.unwrap(Session.class);
		Blob blob = Hibernate.createBlob(blobBytes, session);
		e.setImageBlob(blob);
		
		/* Alternative way to create blob without using hibernate, but direct jdbc connection.
		final byte[] fBytes = blobBytes;
		final Image fImage = e;
		session.doWork(new Work() {		
			@Override
			public void execute(Connection connection) throws SQLException {
				Blob blob = connection.createBlob();
				blob.setBytes(1, fBytes);
				fImage.setImageBlob(blob);				
			}
		});		
		*/
		
//		// Work around to unable to unwrap ThreadLocalSessionContext session.
//		Blob blob = NonContextualLobCreator.INSTANCE.createBlob(blobBytes);
//		e.setImageBlob(blob);
		
		entityManager.persist(e);
		System.out.println("Saved entity " + e);
	}

	private void runQuery() {
		List<?> resultList = entityManager.createQuery("from Image e").getResultList();
		println(resultList);
	}

	public static void println(List<?> list) {
		for (Object object : list) {
			if (object instanceof Object[]) {
				System.out.println(Arrays.asList((Object[])object));
			} else {
				System.out.println(object);
			}
		}
	}
}
